#include "stdafx.h"


#define SAFECALL(x) error = x; if(error != ERROR_SUCCESS) throw error

Registry::Registry(HKEY K) :
	mSubKey(nullptr),
	mKey(nullptr)
{
	long error;
	SAFECALL( RegOpenKeyEx(K, nullptr, 0, KEY_ALL_ACCESS, &mKey) );
}


Registry::~Registry(void)
{
	if(mSubKey != nullptr)
		RegCloseKey(mSubKey);

	RegCloseKey(mKey);
}


void Registry::OpenPath(std::wstring path)
{
	long error;
	if(mSubKey != nullptr)
	{
		SAFECALL( RegCloseKey(mSubKey) );
		mSubKey = nullptr;
	}

	SAFECALL( RegOpenKeyEx(mKey, path.c_str(), 0, KEY_ALL_ACCESS, &mSubKey) );
}


void Registry::OpenSubPath(std::wstring path)
{
	long error;
	auto tmp = mSubKey;

	SAFECALL( RegOpenKeyEx(mSubKey, path.c_str(), 0, KEY_ALL_ACCESS, &mSubKey) );
	RegCloseKey(tmp);
}


void Registry::CreateAndOpenKey(std::wstring name)
{
	long error;
	HKEY key;
	SAFECALL( RegCreateKeyEx(mSubKey, name.c_str(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &key, nullptr) );
	SAFECALL( RegCloseKey(mSubKey) );
	mSubKey = key;
}


void Registry::NewKey(std::wstring name)
{
	long error;
	HKEY key;
	SAFECALL( RegCreateKeyEx(mSubKey, name.c_str(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &key, nullptr) );
	SAFECALL( RegCloseKey(key) );
}

template <>
void Registry::AddAttribute(std::wstring name, int value)
{
	long error;	
	SAFECALL( RegSetKeyValue(mSubKey, nullptr, name.c_str(), REG_DWORD, &value, sizeof(value)) );
}

template <>
void Registry::AddAttribute(std::wstring name, long value)
{
	long error;	
	SAFECALL( RegSetKeyValue(mSubKey, nullptr, name.c_str(), REG_DWORD, &value, sizeof(value)) );
}


template <>
void Registry::AddAttribute(std::wstring name, std::wstring value)
{
	long error;	
	SAFECALL( RegSetValueEx(mSubKey, name.c_str(), 0, REG_SZ, (PBYTE)value.c_str(), (value.length()+1) * sizeof(TCHAR)) );
}


bool Registry::KeyExists(std::wstring path)
{
	HKEY tmp;
	auto error = RegOpenKeyEx(mSubKey ? mSubKey : mKey, path.c_str(), 0, KEY_ALL_ACCESS, &tmp);
	if(error == ERROR_SUCCESS)
	{
		RegCloseKey(tmp);
		return true;
	}

	return false;
}


bool Registry::AttributeExists(std::wstring attribute)
{
	return RegGetValue(mSubKey, _T(""), attribute.c_str(), RRF_RT_ANY, nullptr, nullptr, nullptr) == ERROR_SUCCESS;
}


void Registry::DeleteKey(std::wstring name)
{
	long error;
	SAFECALL( RegDeleteKey(mSubKey, name.c_str()) );
}


void Registry::DeleteAttribute(std::wstring name)
{
	long error;
	SAFECALL( RegDeleteValue(mSubKey, name.c_str()) );
}

template <>
int Registry::GetAttribute(std::wstring name)
{
	int ret = 0;
	long error;	
	SAFECALL( RegGetValue(mSubKey, nullptr, name.c_str(), REG_DWORD, nullptr, &ret, nullptr) );

	return ret;
}

template <>
long Registry::GetAttribute(std::wstring name)
{
	long ret;
	long error;	
	SAFECALL( RegGetValue(mSubKey, nullptr, name.c_str(), REG_DWORD, nullptr, &ret, nullptr) );
	
	return ret;
}


template <>
std::wstring Registry::GetAttribute(std::wstring name)
{
	wchar_t buffer[MAX_PATH+1];
	DWORD length = MAX_PATH;
	long error;	
	SAFECALL( RegGetValue(mSubKey, nullptr, name.c_str(), RRF_RT_REG_SZ, nullptr, buffer, &length) );

	return std::wstring(buffer);
}